Skip to content

Automated WCAG 2.1 AA a11y testing across all themes/modes - #38

Merged
anneke merged 58 commits into
mainfrom
feat/a11y-testing
Sep 22, 2026
Merged

anneke merged 58 commits into
mainfrom
feat/a11y-testing

Conversation

@sjoerdbeentjes

@sjoerdbeentjes sjoerdbeentjes commented Jun 22, 2026 •

Copy link
Copy Markdown
Collaborator

Adds an automated WCAG 2.1 AA pipeline that sweeps every Storybook story across all themes and modes from @surfnet/tokens, in both React and Angular.

What

  • Shared config in @surfnet/storybook-config: browser-safe a11yParameters (merged into both previews, also scopes the addon-a11y panel) and a node-only runStoryA11yAudit behind a ./test-runner subpath so it never enters a preview bundle.
  • Builder-agnostic runner: @storybook/test-runner + axe-playwright against a served Storybook, so one setup covers React (Vite) and Angular (webpack). Each story is audited once per theme × mode (11 themes × 2 modes), writing a per-story JSON report.
  • Wiring: per-package test:a11y / test:a11y:ci scripts, a turbo task, a root script, and a CI step that runs report-only (continue-on-error) and uploads the JSON as an artifact.

Notes

  • CI is intentionally report-only until the token contrast backlog is triaged; flip to blocking by removing continue-on-error.

@sjoerdbeentjes
sjoerdbeentjes force-pushed the feat/a11y-testing branch 5 times, most recently from b563368 to 871c744 Compare June 22, 2026 14:18
@github-actions

github-actions Bot commented Jun 22, 2026 •

Copy link
Copy Markdown
Contributor

♿ Accessibility audit — WCAG 2.2 AA

⚠️ 114 finding(s) — 114 contrast (per theme·mode), 0 theme-independent · across 359 stories / 10052 audited combinations. Report-only — does not block merge.

⏭️ 37 story(ies) safe to skip in manual review — color-contrast only
  • @surfnet/curve-angular → Alert → Danger
  • @surfnet/curve-angular → Alert → Variants
  • @surfnet/curve-angular → Badge → Default
  • @surfnet/curve-angular → Badge → Status List
  • @surfnet/curve-angular → Badge → Variants
  • @surfnet/curve-angular → Button → Default
  • @surfnet/curve-angular → Button → Sizes
  • @surfnet/curve-angular → Button → Variants
  • @surfnet/curve-angular → Button → With Icon
  • @surfnet/curve-angular → Calendar → Default
  • @surfnet/curve-angular → Calendar → Multiple
  • @surfnet/curve-angular → DataTable → Custom Toolbar
  • @surfnet/curve-angular → Empty → Default
  • @surfnet/curve-angular → Empty → With Multiple Actions
  • @surfnet/curve-angular → Item → With Header And Footer
  • @surfnet/curve-angular → Pagination → Numbered Pagination
  • @surfnet/curve-angular → Sidebar → Default
  • @surfnet/curve-angular → Tabs → Default
  • @surfnet/curve-react → Alert → Danger
  • @surfnet/curve-react → Alert → Variants
  • @surfnet/curve-react → Badge → Default
  • @surfnet/curve-react → Badge → Status List
  • @surfnet/curve-react → Badge → Variants
  • @surfnet/curve-react → Button → Default
  • @surfnet/curve-react → Button → Sizes
  • @surfnet/curve-react → Button → Variants
  • @surfnet/curve-react → Button → With Icon
  • @surfnet/curve-react → Calendar → Dropdown Caption
  • @surfnet/curve-react → Calendar → In Card
  • @surfnet/curve-react → Calendar → Single
  • @surfnet/curve-react → Card → Default
  • @surfnet/curve-react → DataTable → Custom Toolbar
  • @surfnet/curve-react → Empty → Default
  • @surfnet/curve-react → Empty → With Multiple Actions
  • @surfnet/curve-react → Item → With Header And Footer
  • @surfnet/curve-react → Sidebar → Default
  • @surfnet/curve-react → Tabs → Default
@surfnet/curve-angular — 90 finding(s)
Alert — 6 finding(s) · color-contrast only
Danger — 3 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • dark — #a3a3a3 on #721c18 · ratio 4.39 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/dark)
  • shadcn-default
    • dark — #a3a3a3 on #721c18 · ratio 4.39 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (shadcn-default/dark)
  • shadcn-default-grey-background
    • dark — #a3a3a3 on #721c18 · ratio 4.39 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (shadcn-default-grey-background/dark)
Variants — 3 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • dark — #a3a3a3 on #01653d · ratio 2.84 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/dark)
  • shadcn-default
    • dark — #a3a3a3 on #01653d · ratio 2.84 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (shadcn-default/dark)
  • shadcn-default-grey-background
    • dark — #a3a3a3 on #01653d · ratio 2.84 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (shadcn-default-grey-background/dark)
Badge — 3 finding(s) · color-contrast only
Default — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
Status List — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
Variants — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
Button — 4 finding(s) · color-contrast only
Default — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
Sizes — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
Variants — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
With Icon — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
Calendar — 56 finding(s) · color-contrast only
Default — 28 finding(s) · color-contrast only — skippable
  • default
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (default/light)
    • dark — #6f6f6f on #0a0a0a · ratio 3.94 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (default/dark)
  • groenvermogen-nkph2
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
    • dark — #575757 on #0a0a0a · ratio 2.73 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/dark)
  • shadcn-default
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (shadcn-default/light)
    • dark — #575757 on #0a0a0a · ratio 2.73 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (shadcn-default/dark)
  • shadcn-default-grey-background
    • light — #a4a4a4 on #f5f5f5 · ratio 2.28 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (shadcn-default-grey-background/light)
    • dark — #575757 on #0a0a0a · ratio 2.73 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (shadcn-default-grey-background/dark)
  • surf-blue-purple
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-blue-purple/light)
    • dark — #6f6f6f on #0a0a0a · ratio 3.94 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-blue-purple/dark)
  • surf-blue-turquoise
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-blue-turquoise/light)
    • dark — #6f6f6f on #0a0a0a · ratio 3.94 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-blue-turquoise/dark)
  • surf-blue-yellow
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-blue-yellow/light)
    • dark — #6f6f6f on #0a0a0a · ratio 3.94 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-blue-yellow/dark)
  • surf-green
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-green/light)
    • dark — #6f6f6f on #0a0a0a · ratio 3.94 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-green/dark)
  • surf-orange
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-orange/light)
    • dark — #6f6f6f on #0a0a0a · ratio 3.94 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-orange/dark)
  • surf-orange-turquoise
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-orange-turquoise/light)
    • dark — #6f6f6f on #0a0a0a · ratio 3.94 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-orange-turquoise/dark)
  • surf-pilot
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-pilot/light)
    • dark — #6f6f6f on #0a0a0a · ratio 3.94 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-pilot/dark)
  • surf-purple
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-purple/light)
    • dark — #6f6f6f on #0a0a0a · ratio 3.94 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-purple/dark)
  • surf-purple-orange
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-purple-orange/light)
    • dark — #6f6f6f on #0a0a0a · ratio 3.94 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-purple-orange/dark)
  • surf-yellow
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-yellow/light)
    • dark — #6f6f6f on #0a0a0a · ratio 3.94 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-yellow/dark)
Multiple — 28 finding(s) · color-contrast only — skippable
  • default
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (default/light)
    • dark — #6f6f6f on #0a0a0a · ratio 3.94 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (default/dark)
  • groenvermogen-nkph2
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
    • dark — #575757 on #0a0a0a · ratio 2.73 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/dark)
  • shadcn-default
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (shadcn-default/light)
    • dark — #575757 on #0a0a0a · ratio 2.73 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (shadcn-default/dark)
  • shadcn-default-grey-background
    • light — #a4a4a4 on #f5f5f5 · ratio 2.28 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (shadcn-default-grey-background/light)
    • dark — #575757 on #0a0a0a · ratio 2.73 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (shadcn-default-grey-background/dark)
  • surf-blue-purple
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-blue-purple/light)
    • dark — #6f6f6f on #0a0a0a · ratio 3.94 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-blue-purple/dark)
  • surf-blue-turquoise
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-blue-turquoise/light)
    • dark — #6f6f6f on #0a0a0a · ratio 3.94 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-blue-turquoise/dark)
  • surf-blue-yellow
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-blue-yellow/light)
    • dark — #6f6f6f on #0a0a0a · ratio 3.94 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-blue-yellow/dark)
  • surf-green
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-green/light)
    • dark — #6f6f6f on #0a0a0a · ratio 3.94 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-green/dark)
  • surf-orange
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-orange/light)
    • dark — #6f6f6f on #0a0a0a · ratio 3.94 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-orange/dark)
  • surf-orange-turquoise
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-orange-turquoise/light)
    • dark — #6f6f6f on #0a0a0a · ratio 3.94 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-orange-turquoise/dark)
  • surf-pilot
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-pilot/light)
    • dark — #6f6f6f on #0a0a0a · ratio 3.94 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-pilot/dark)
  • surf-purple
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-purple/light)
    • dark — #6f6f6f on #0a0a0a · ratio 3.94 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-purple/dark)
  • surf-purple-orange
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-purple-orange/light)
    • dark — #6f6f6f on #0a0a0a · ratio 3.94 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-purple-orange/dark)
  • surf-yellow
    • light — #a9a9a9 on #ffffff · ratio 2.35 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-yellow/light)
    • dark — #6f6f6f on #0a0a0a · ratio 3.94 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-yellow/dark)
DataTable — 1 finding(s) · color-contrast only
Custom Toolbar — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
Empty — 2 finding(s) · color-contrast only
Default — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
With Multiple Actions — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
Item — 1 finding(s) · color-contrast only
With Header And Footer — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
Pagination — 14 finding(s) · color-contrast only
Numbered Pagination — 14 finding(s) · color-contrast only — skippable
  • default
    • dark — #4a5565 on #0a0a0a · ratio 2.61 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (default/dark)
  • groenvermogen-nkph2
    • dark — #4a5565 on #0a0a0a · ratio 2.61 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/dark)
  • shadcn-default
    • dark — #4a5565 on #0a0a0a · ratio 2.61 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (shadcn-default/dark)
  • shadcn-default-grey-background
    • dark — #4a5565 on #0a0a0a · ratio 2.61 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (shadcn-default-grey-background/dark)
  • surf-blue-purple
    • dark — #4a5565 on #0a0a0a · ratio 2.61 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-blue-purple/dark)
  • surf-blue-turquoise
    • dark — #4a5565 on #0a0a0a · ratio 2.61 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-blue-turquoise/dark)
  • surf-blue-yellow
    • dark — #4a5565 on #0a0a0a · ratio 2.61 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-blue-yellow/dark)
  • surf-green
    • dark — #4a5565 on #0a0a0a · ratio 2.61 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-green/dark)
  • surf-orange
    • dark — #4a5565 on #0a0a0a · ratio 2.61 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-orange/dark)
  • surf-orange-turquoise
    • dark — #4a5565 on #0a0a0a · ratio 2.61 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-orange-turquoise/dark)
  • surf-pilot
    • dark — #4a5565 on #0a0a0a · ratio 2.61 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-pilot/dark)
  • surf-purple
    • dark — #4a5565 on #0a0a0a · ratio 2.61 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-purple/dark)
  • surf-purple-orange
    • dark — #4a5565 on #0a0a0a · ratio 2.61 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-purple-orange/dark)
  • surf-yellow
    • dark — #4a5565 on #0a0a0a · ratio 2.61 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-yellow/dark)
Sidebar — 2 finding(s) · color-contrast only
Default — 2 finding(s) · color-contrast only — skippable
  • surf-blue-yellow
    • dark — #fafafa on #8a7900 · ratio 4.17 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-blue-yellow/dark)
  • surf-yellow
    • dark — #fafafa on #8a7900 · ratio 4.17 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-yellow/dark)
Tabs — 1 finding(s) · color-contrast only
Default — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)

@surfnet/curve-react — 24 finding(s)
Alert — 6 finding(s) · color-contrast only
Danger — 3 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • dark — #a3a3a3 on #721c18 · ratio 4.39 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/dark)
  • shadcn-default
    • dark — #a3a3a3 on #721c18 · ratio 4.39 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (shadcn-default/dark)
  • shadcn-default-grey-background
    • dark — #a3a3a3 on #721c18 · ratio 4.39 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (shadcn-default-grey-background/dark)
Variants — 3 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • dark — #a3a3a3 on #01653d · ratio 2.84 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/dark)
  • shadcn-default
    • dark — #a3a3a3 on #01653d · ratio 2.84 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (shadcn-default/dark)
  • shadcn-default-grey-background
    • dark — #a3a3a3 on #01653d · ratio 2.84 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (shadcn-default-grey-background/dark)
Badge — 3 finding(s) · color-contrast only
Default — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
Status List — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
Variants — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
Button — 4 finding(s) · color-contrast only
Default — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
Sizes — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
Variants — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
With Icon — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
Calendar — 3 finding(s) · color-contrast only
Dropdown Caption — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
In Card — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
Single — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
Card — 1 finding(s) · color-contrast only
Default — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
DataTable — 1 finding(s) · color-contrast only
Custom Toolbar — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
Empty — 2 finding(s) · color-contrast only
Default — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
With Multiple Actions — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
Item — 1 finding(s) · color-contrast only
With Header And Footer — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)
Sidebar — 2 finding(s) · color-contrast only
Default — 2 finding(s) · color-contrast only — skippable
  • surf-blue-yellow
    • dark — #fafafa on #8a7900 · ratio 4.17 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-blue-yellow/dark)
  • surf-yellow
    • dark — #fafafa on #8a7900 · ratio 4.17 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (surf-yellow/dark)
Tabs — 1 finding(s) · color-contrast only
Default — 1 finding(s) · color-contrast only — skippable
  • groenvermogen-nkph2
    • light — #fafafa on #84cc16 · ratio 1.89 — color-contrast (1.4.3)
      color-contrast (1.4.3) violation (groenvermogen-nkph2/light)

Automated axe covers ~30–50% of WCAG 2.2 AA. Keyboard, screen-reader and reflow checks still need a manual pass. Full per-story JSON is in the run’s a11y-reports artifact.

@sjoerdbeentjes sjoerdbeentjes linked an issue Jun 23, 2026 that may be closed by this pull request
@sjoerdbeentjes
sjoerdbeentjes force-pushed the feat/a11y-testing branch 3 times, most recently from 8b13cff to fc78595 Compare June 30, 2026 06:45
@sjoerdbeentjes
sjoerdbeentjes force-pushed the feat/a11y-testing branch 4 times, most recently from 52bcb10 to 5afc87c Compare July 1, 2026 18:46
Comment thread .github/workflows/ci.yml

# Scoped to @surfnet/storybook-config, which pins playwright, so both
# framework runs share one browser.
- name: Install Playwright Chromium

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hoe is de performance? Ik zou verwachten dat we in een CI-stap een headless browser gebruiken.

@sjoerdbeentjes
sjoerdbeentjes force-pushed the feat/a11y-testing branch 2 times, most recently from 573772a to 4c66f62 Compare July 6, 2026 07:43
github-actions Bot added a commit that referenced this pull request Jul 6, 2026
github-actions Bot added a commit that referenced this pull request Jul 6, 2026
github-actions Bot added a commit that referenced this pull request Jul 6, 2026
github-actions Bot added a commit that referenced this pull request Jul 7, 2026
github-actions Bot added a commit that referenced this pull request Jul 14, 2026
github-actions Bot added a commit that referenced this pull request Aug 25, 2026
github-actions Bot added a commit that referenced this pull request Sep 21, 2026
github-actions Bot added a commit that referenced this pull request Sep 21, 2026
github-actions Bot added a commit that referenced this pull request Sep 21, 2026
anneke and others added 8 commits September 22, 2026 10:03
The Default story rendered a bare switch with no visible label or
aria-label, failing the aria-toggle-field-name a11y check.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Select's role="combobox" trigger does not take its name from visible
content (name-from-author only per ARIA), so the placeholder/value
text inside SelectValue was never exposed as an accessible name.
Added aria-label to the trigger in each story.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
ComboboxChipRemove had no accessible name, unlike ComboboxClear which
already defaults to "Clear". Added a removeLabel prop (default
"Remove") and used a per-chip label in the Multiple story.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Base UI's ToggleGroup renders role="group" but also sets
aria-orientation on the root, which isn't a valid attribute for that
role per the ARIA spec (aria-allowed-attr). Unset it explicitly since
data-orientation already drives the visual layout.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
react-resizable-panels always wraps panel content in an overflow:auto
div. The Sidebar/Inspector panels were narrower than their unbreakable
label text, creating a scrollable-but-unfocusable region
(scrollable-region-focusable). Added min-w-0 + truncate so the content
no longer overflows.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
_values fell back to [min, max] whenever value/defaultValue was a
plain number instead of an array, so every single-value slider
rendered a second, unlabeled ghost thumb alongside the real one.
Fixed the fallback to a single-value array, and forwarded aria-label /
getAriaLabel to each Slider.Thumb (a root-level aria-label doesn't
reach the underlying range inputs).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The month/year select triggers use role="combobox", which takes its
name from author (aria-label) only, not from content — so the visible
"Sep"/"2026" text wasn't exposed as an accessible name. Added
aria-label to both triggers.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Base UI's Root props don't include Thumb-only props like
getAriaLabel, so it needs an explicit type extension for tsc to
accept it being forwarded from Slider to Slider.Thumb.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
github-actions Bot added a commit that referenced this pull request Sep 22, 2026
@anneke
anneke marked this pull request as ready for review September 22, 2026 08:44
@anneke
anneke merged commit 198f917 into main Sep 22, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WCAG 2.1 AA-check op alle PoC-componenten

3 participants